package com.lonwin.mes2u8.service;

import com.alibaba.fastjson.JSONObject;
import com.alibaba.fastjson.TypeReference;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import com.lonwin.mes2u8.common.CommonValue;
import com.lonwin.mes2u8.common.MesConfig;
import com.lonwin.mes2u8.common.YonYouConfig;
import com.lonwin.mes2u8.domain.mes.MesCommonResult;
import com.lonwin.mes2u8.domain.mes.MesProductionQueryResult;
import com.lonwin.mes2u8.domain.u8.*;
import com.lonwin.mes2u8.util.BaseInfoU8;
import com.lonwin.mes2u8.util.MyHttpClientUtil;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.math.BigDecimal;
import java.util.*;
import java.util.stream.Collectors;

/**
 * @author DELL
 * @Date 2023-12-18 15:07
 */
@Service
@Slf4j
public class ProductionAppService {

    @Resource
    private YonYouConfig yonYouConfig;
    @Resource
    private MesConfig mesConfig;
    @Resource
    private MesTokenService mesTokenService;


    /**
     * mes根据成品入库单编号查询成品入库单详情
     *
     * @param id 成品入库单编号
     * @return 成品入库单详情
     */
    public List<MesProductionQueryResult> getMesProductionInfo(String id) {
        Map<String, String> mesMaterialOutQueryParamMap = Maps.newHashMapWithExpectedSize(1);
        mesMaterialOutQueryParamMap.put("sno", id);
        String mesMaterialOutQueryResultString = MyHttpClientUtil.sendPostRequest(
                mesConfig.getAddress() + mesConfig.getProductionInfoUrl(),
                mesTokenService.buildTokenHeader(),
                JSONObject.toJSONString(mesMaterialOutQueryParamMap),
                MyHttpClientUtil::handleJsonResponse
        );

        MesCommonResult<List<MesProductionQueryResult>> commonResult = JSONObject.parseObject(mesMaterialOutQueryResultString, new TypeReference<MesCommonResult<List<MesProductionQueryResult>>>() {
        }.getType());

        List<MesProductionQueryResult> resultList = Lists.newArrayList();
        if (Objects.nonNull(commonResult) && commonResult.isSuccess() && Objects.nonNull(commonResult.getResult()) && !commonResult.getResult().isEmpty()) {
            List<MesProductionQueryResult> result = commonResult.getResult();
            for (Object mesProductionQueryResult : result) {
                MesProductionQueryResult mesProductionQueryResult1 = JSONObject.parseObject(JSONObject.toJSONString(mesProductionQueryResult), MesProductionQueryResult.class);
                resultList.add(mesProductionQueryResult1);
            }
            return resultList;
        }

        return Lists.newArrayList();
    }

    /**
     * 查询U8成品入库单详情
     *
     * @param productionId U8成品入库单编号
     * @return 判断结果
     */
    public U8ProductionQueryResultInfo findU8ProductionInfo(String productionId) {
        U8CommonHeader commonHeader = U8CommonHeader.builder()
                .from_account(yonYouConfig.getFromAccount())
                .to_account(yonYouConfig.getToAccount())
                .app_key(yonYouConfig.getAppKey())
                .token(BaseInfoU8.getToken())
                .build();

        String respString = MyHttpClientUtil.sendSSLGetRequest(
                yonYouConfig.getAddress() + yonYouConfig.getProductionGetUrl(),
                MyHttpClientUtil.convertGetParamByObj(commonHeader) + "&id=" + productionId,
                MyHttpClientUtil::handleJsonResponse
        );

        U8ProductionQueryResult result = JSONObject.parseObject(respString, U8ProductionQueryResult.class);

        return Objects.nonNull(result) && CommonValue.U8_RESPONSE_SUCCESS.equals(result.getErrcode()) && Objects.nonNull(result.getProductin()) ? result.getProductin() : null;
    }

    /**
     * 判断成品入库单是否未被录入
     *
     * @param productionId mes成品入库单编号
     * @return 判断结果
     */
    public boolean isNotExistOnU8(String productionId) {
        return Objects.isNull(findU8ProductionInfo(productionId));
    }


    /**
     * 向U8中添加成品入库单
     *
     * @param u8ProductionAddParam 成品入库单添加参数
     * @return 是否添加成功
     */
    public U8CommonSyncResponse addProductionToU8(U8ProductionAddParam u8ProductionAddParam) {
        U8CommonHeader commonHeader = U8CommonHeader.builder()
                .from_account(yonYouConfig.getFromAccount())
                .to_account(yonYouConfig.getToAccount())
                .app_key(yonYouConfig.getAppKey())
                .tradeid(BaseInfoU8.getTradeId())
                .token(BaseInfoU8.getToken())
                .build();

        String respString = MyHttpClientUtil.sendSSLPostRequest(
                yonYouConfig.getAddress() + yonYouConfig.getProductionAddUrl() + "?" + MyHttpClientUtil.convertGetParamByObj(commonHeader),
                null,
                JSONObject.toJSONString(u8ProductionAddParam),
                MyHttpClientUtil::handleJsonResponse
        );

        U8CommonSyncResponse u8AddSyncResponse = JSONObject.parseObject(respString, U8CommonSyncResponse.class);

        return u8AddSyncResponse;
    }

    public U8ProductionHandlerResult handleMesProductionQueryResultOfGroup(List<MesProductionQueryResult> mesProductionInfo) {
        if (Objects.isNull(mesProductionInfo) || mesProductionInfo.isEmpty()) {
            return null;
        }

        Map<String, List<MesProductionQueryResult>> mesInventoryGroup = mesProductionInfo.stream().collect(Collectors.groupingBy(MesProductionQueryResult::getSpono));

        List<U8ProductionHandlerResultInfo> u8ProductionHandlerResultInfoList = Lists.newArrayList();

        for (Map.Entry<String, List<MesProductionQueryResult>> groupEntry : mesInventoryGroup.entrySet()) {
            BigDecimal sumWeight = groupEntry.getValue().stream().map(MesProductionQueryResult::getSingleWeight).reduce(BigDecimal.ZERO, BigDecimal::add);
            BigDecimal sumNumber = groupEntry.getValue().stream().map(MesProductionQueryResult::getNum).reduce(BigDecimal.ZERO, BigDecimal::add);
            if (sumWeight.compareTo(BigDecimal.ZERO) == 0) {
                // 表示这个存货没有库存，不需要添加到
                continue;
            }
            U8ProductionHandlerResultInfo info = new U8ProductionHandlerResultInfo();
            info.setInventorycode(groupEntry.getKey());
            info.setQuantity(sumWeight);
            info.setNumber(sumNumber);
            u8ProductionHandlerResultInfoList.add(info);
        }

        U8ProductionHandlerResult u8ProductionHandlerResult = new U8ProductionHandlerResult();
        u8ProductionHandlerResult.setBatchCode(mesProductionInfo.get(0).getSno());
        u8ProductionHandlerResult.setInfoList(u8ProductionHandlerResultInfoList);

        return u8ProductionHandlerResult;

    }

    public List<U8ProductionBatchGetResultInfo> findU8ProductionInfoByBatchCode(String batchCode) {
        U8CommonHeader commonHeader = U8CommonHeader.builder()
                .from_account(yonYouConfig.getFromAccount())
                .to_account(yonYouConfig.getToAccount())
                .app_key(yonYouConfig.getAppKey())
                .token(BaseInfoU8.getToken())
                .tradeid(BaseInfoU8.getTradeId())
                .build();

        String respString = MyHttpClientUtil.sendSSLGetRequest(
                yonYouConfig.getAddress() + yonYouConfig.getProductionBatchGetUrl() + "?" + MyHttpClientUtil.convertGetParamByObj(commonHeader) + "&memory=" + batchCode,
                null,
                MyHttpClientUtil::handleJsonResponse
        );

        U8ProductionBatchGetResult u8AddSyncResult = JSONObject.parseObject(respString, U8ProductionBatchGetResult.class);

        if (Objects.isNull(u8AddSyncResult) || Objects.isNull(u8AddSyncResult.getProductinlist()) || u8AddSyncResult.getProductinlist().isEmpty()) {
            log.error("MaterialOutAppService.getU8MaterialOutListByMesBatchCode occur exception, return null : {}", batchCode);
            return null;
        }

        List<U8ProductionBatchGetResultInfo> productionInfoList = u8AddSyncResult.getProductinlist();

        ArrayList<U8ProductionBatchGetResultInfo> result = Lists.newArrayList();
        for (Object batchGetResult : productionInfoList) {
            if (Objects.nonNull(batchGetResult)) {
                result.add(JSONObject.parseObject(JSONObject.toJSONString(batchGetResult), U8ProductionBatchGetResultInfo.class));
            }
        }

        return result;
    }

    public U8ProductionHandlerResult handleU8ProductionQueryResultEntryList(String batchCode, List<U8ProductionBatchGetResultInfo> u8ProductionBatchGetInfos) {

        if (Objects.isNull(u8ProductionBatchGetInfos) || u8ProductionBatchGetInfos.isEmpty()) {
            return null;
        }

        U8ProductionHandlerResult u8LastProductionResult = new U8ProductionHandlerResult();
        u8LastProductionResult.setBatchCode(batchCode);

        List<U8ProductionQueryResultEntry> entryList = Lists.newArrayList();
        if (Objects.nonNull(u8ProductionBatchGetInfos) && !u8ProductionBatchGetInfos.isEmpty()) {
            // 要按照成品入库单列表查找入库单详情

            for (U8ProductionBatchGetResultInfo u8ProductionBatchGetInfo : u8ProductionBatchGetInfos) {
                U8ProductionQueryResultInfo u8ProductionInfo = findU8ProductionInfo(u8ProductionBatchGetInfo.getCode());
                entryList.addAll(u8ProductionInfo.getEntry());
            }
        }

        Map<String, List<U8ProductionHandlerResultInfo>> u8ProductionInventoryGroup = entryList.stream().map(U8ProductionQueryResultEntry::convertU8ProductionHandlerResultInfo)
                .collect(Collectors.groupingBy(U8ProductionHandlerResultInfo::getInventorycode));

        List<U8ProductionHandlerResultInfo> u8LastProductionInfoList = Lists.newArrayList();
        for (Map.Entry<String, List<U8ProductionHandlerResultInfo>> u8ProductionInventoryGroupEntry : u8ProductionInventoryGroup.entrySet()) {
            BigDecimal amount = u8ProductionInventoryGroupEntry.getValue().stream().map(U8ProductionHandlerResultInfo::getQuantity).reduce(BigDecimal.ZERO, BigDecimal::add);

            if (amount.compareTo(BigDecimal.ZERO) > 0) {
                U8ProductionHandlerResultInfo resInfo = new U8ProductionHandlerResultInfo();
                resInfo.setInventorycode(u8ProductionInventoryGroupEntry.getKey());
                resInfo.setQuantity(amount);
                u8LastProductionInfoList.add(resInfo);
            }
        }

        u8LastProductionResult.setInfoList(u8LastProductionInfoList);

        return u8LastProductionResult;
    }
}
